/**
 * Created by IntelliJ IDEA.
 * User: scotthatcher
 * Date: Mar 23, 2010
 * Time: 11:40:46 AM
 * To change this template use File | Settings | File Templates.
 */
import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Breakout extends GraphicsProgram {

    /** Width and height of application window in pixels */
    public static final int APPLICATION_WIDTH = 400;
    public static final int APPLICATION_HEIGHT = 600;

    /** Dimensions of game board (usually the same) */
    private static final int WIDTH = APPLICATION_WIDTH;
    private static final int HEIGHT = APPLICATION_HEIGHT;

    /** Dimensions of the paddle */
    private static final int PADDLE_WIDTH = 60;
    private static final int PADDLE_HEIGHT = 10;

    /** Offset of the paddle up from the bottom */
    private static final int PADDLE_Y_OFFSET = 30;

    /** Number of bricks per row */
    private static final int NBRICKS_PER_ROW = 10;

    /** Number of rows of bricks */
    private static final int NBRICK_ROWS = 10;

    /** Separation between bricks */
    private static final int BRICK_SEP = 4;

    /** Width of a brick */
    private static final int BRICK_WIDTH = (WIDTH - (NBRICKS_PER_ROW - 1) * BRICK_SEP) / NBRICKS_PER_ROW;

    /** Height of a brick */
    private static final int BRICK_HEIGHT = 8;

    /** Radius of the ball in pixels */
    private static final int BALL_RADIUS = 10;

    /** Offset of the top brick row from the top */
    private static final int BRICK_Y_OFFSET = 70;

    /** Number of turns */
    private static final int NTURNS = 3;

    /** Amount Y velocity is increased each cycle as a
     * result of gravity */
    private static final double GRAVITY = 3;

    /** Animation delay or pause time between ball moves */
    private static final int DELAY = 50;

    /** Initial X and Y location of ball */
    private static final double X_START = WIDTH / 2;
    private static final double Y_START = HEIGHT/2;

    /** X Velocity */
    private static final double X_VEL = 3;


    //private double Y_VEL = rgen.nextInt(0,WIDTH);


    /** Starting X and Y Velocities */
     private double xVel = X_VEL;
     private double yVel;
  

    private void SetupPaddle(){
        Paddle = new GRect((APPLICATION_WIDTH - PADDLE_WIDTH)/2, APPLICATION_HEIGHT-PADDLE_Y_OFFSET, PADDLE_WIDTH, PADDLE_HEIGHT);
		Paddle.setFilled(true);
        add (Paddle);
    }


    public void run() {
        SetupBricks();
        SetupPaddle();
        CreateBall();
        addMouseListeners();
        yVel = rgen.nextDouble(0,8);
        while (1 == 1) {
			moveBall();
			checkForCollision_X();
            checkForCollision_Y();
			pause(DELAY);
        }
        
    }

    private void SetupBricks(){
        int RowNumber = 0;
        for (int j = 0; j < NBRICK_ROWS; j++)  {
            for (int i = 0; i < NBRICKS_PER_ROW; i++)  {
                double XLocation = (i*BRICK_WIDTH)+(i*BRICK_SEP);
                double YLocation = BRICK_Y_OFFSET + (RowNumber*BRICK_HEIGHT) + (RowNumber*BRICK_SEP);
                GRect Brick = new GRect(XLocation,YLocation,BRICK_WIDTH,BRICK_HEIGHT);
                Brick.setFilled(true);

                if      (RowNumber<2)  Brick.setColor(Color.red);
                else if (RowNumber<4)  Brick.setColor(Color.orange);
                else if (RowNumber<6)  Brick.setColor(Color.yellow);
                else if (RowNumber<8)  Brick.setColor(Color.green);
                else                   Brick.setColor(Color.cyan);
                add (Brick);

            }
            RowNumber++;
    }
    }
    // Called on mouse press to record the coordinates of the click */
	public void mousePressed(MouseEvent e) {
		// GPoint has X and Y coordinate
		last = new GPoint(e.getPoint());
		gobj = getElementAt(last);
}

    // Called on mouse drag to reposition the object
    public void mouseDragged(MouseEvent e) {
    if (gobj != null && e.getX() <= APPLICATION_WIDTH && e.getX() > 0 && gobj == Paddle) {
        gobj.move(e.getX() - last.getX(),0);
        last = new GPoint(e.getPoint());
    }
    }
    private void CreateBall(){
        ball = new GOval(X_START,Y_START ,BALL_RADIUS,BALL_RADIUS);
        ball.setFilled(true);
        add (ball);
    }
   private void moveBall() {
		// increase yVelocity due to gravity on each cycle
		//yVel = rgen.nextInt(0,HEIGHT);
       //xVel = GRAVITY;
		ball.move(xVel,yVel);
		}

	/** Determine if collision with floor, update velocities
	 * and location as appropriate. */
	private void checkForCollision_Y() {
		// determine if ball has dropped below the floor
		if (ball.getY() >= HEIGHT - BALL_RADIUS || ball.getY() <= 0) {

	// change ball's Y velocity to now bounce upwards
			yVel = -yVel;

			// assume bounce will move ball an amount above the
			// floor equal to the amount it would have dropped
			// below the floor.
			double diff = (ball.getY() - HEIGHT - BALL_RADIUS);
			ball.move(0, yVel * diff);
			}
        if (ball.getY() <= 0){
            yVel = -yVel;
            double diff = (ball.getY() + BALL_RADIUS);
            ball.move(0,yVel * diff);
        }
        if (gobj==Paddle){
            yVel = -yVel;
            double diff = ball.getY() - (HEIGHT - PADDLE_Y_OFFSET);
            ball.move(0,yVel);
        }
    }
    private void checkForCollision_X() {
            // determine if ball has dropped below the floor
            if (ball.getX() >= WIDTH - BALL_RADIUS) {

        // change ball's Y velocity to now bounce upwards
                xVel = -xVel;

                // assume bounce will move ball an amount above the
                // floor equal to the amount it would have dropped
                // below the floor.
                double diff = (ball.getX() - WIDTH - BALL_RADIUS);
                ball.move(xVel * diff, 0);
                }
            if (ball.getX() <= 0){
                xVel = -xVel;
                double diff = (ball.getX() + BALL_RADIUS);
                ball.move(xVel * diff, 0);
            }


   /* private void checkForCollision() {
		// determine if ball has dropped below the floor
		if (ball.getY() > getHeight() - DIAM_BALL) {

	// change ball's Y velocity to now bounce upwards
			yVel = -yVel * BOUNCE_REDUCE;

			// assume bounce will move ball an amount above the
			// floor equal to the amount it would have dropped
			// below the floor.
			double diff = ball.getY() - (getHeight() - DIAM_BALL);
			ball.move(0, -2 * diff);
			}
		}   */
}

    private GObject gobj;	//The object being dragged
	private GPoint last;	//The last mouse position
	private RandomGenerator rgen = RandomGenerator.getInstance();
    private GOval ball;
    private GRect Paddle;
}